home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Resources / Online / Term / Extras / Source / term-source.lha / Lists.c < prev    next >
C/C++ Source or Header  |  1996-10-20  |  8KB  |  476 lines

  1. /*
  2. **    Lists.c
  3. **
  4. **    Generic list management routines
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "Global.h"
  14. #endif
  15.  
  16.     /* ClearGenericList(struct GenericList *List):
  17.      *
  18.      *    Clear a generic list, free its contents.
  19.      */
  20.  
  21. VOID
  22. ClearGenericList(struct GenericList *List,BOOL Notify)
  23. {
  24.     ObtainSemaphore(&List->ListSemaphore);
  25.  
  26.     if(List->Notify && Notify)
  27.         (*List->Notify)(List,0);
  28.  
  29.     FreeList((struct List *)&List->ListHeader);
  30.  
  31.     List->ListNode = NULL;
  32.     List->ListOffset = -1;
  33.     List->ListCount = 0;
  34.  
  35.     if(List->Notify && Notify)
  36.         (*List->Notify)(List,1);
  37.  
  38.     ReleaseSemaphore(&List->ListSemaphore);
  39. }
  40.  
  41.     /* CreateGenericList():
  42.      *
  43.      *    Create a generic list.
  44.      */
  45.  
  46. struct GenericList *
  47. CreateGenericList()
  48. {
  49.     struct GenericList *List;
  50.  
  51.     if(List = (struct GenericList *)AllocVecPooled(sizeof(struct GenericList),MEMF_ANY | MEMF_CLEAR))
  52.     {
  53.         NewList((struct List *)&List->ListHeader);
  54.  
  55.         InitSemaphore(&List->ListSemaphore);
  56.  
  57.         List->ListCount = 0;
  58.         List->ListNode = NULL;
  59.         List->ListOffset = -1;
  60.     }
  61.  
  62.     return(List);
  63. }
  64.  
  65.     /* FirstGenericListNode(struct GenericList *List):
  66.      *
  67.      *    Pick the first node in a generic list.
  68.      */
  69.  
  70. struct Node *
  71. FirstGenericListNode(struct GenericList *List)
  72. {
  73.     struct Node *Node;
  74.  
  75.     SafeObtainSemaphoreShared(&List->ListSemaphore);
  76.  
  77.     if(!IsListEmpty((struct List *)List))
  78.     {
  79.         Node = List->ListNode = (struct Node *)List->ListHeader.mlh_Head;
  80.  
  81.         List->ListOffset = 0;
  82.     }
  83.     else
  84.         Node = NULL;
  85.  
  86.     ReleaseSemaphore(&List->ListSemaphore);
  87.  
  88.     return(Node);
  89. }
  90.  
  91.     /* LastGenericListNode(struct GenericList *List):
  92.      *
  93.      *    Pick the last node in a generic list.
  94.      */
  95.  
  96. struct Node *
  97. LastGenericListNode(struct GenericList *List)
  98. {
  99.     struct Node *Node;
  100.  
  101.     SafeObtainSemaphoreShared(&List->ListSemaphore);
  102.  
  103.     if(!IsListEmpty((struct List *)List))
  104.     {
  105.         Node = List->ListNode = (struct Node *)List->ListHeader.mlh_TailPred;
  106.  
  107.         List->ListOffset = List->ListCount - 1;
  108.     }
  109.     else
  110.         Node = NULL;
  111.  
  112.     ReleaseSemaphore(&List->ListSemaphore);
  113.  
  114.     return(Node);
  115. }
  116.  
  117.     /* NextGenericListNode(struct GenericList *List):
  118.      *
  119.      *    Pick the next successive node in a generic list.
  120.      */
  121.  
  122. struct Node *
  123. NextGenericListNode(struct GenericList *List)
  124. {
  125.     struct Node *Node;
  126.  
  127.     SafeObtainSemaphoreShared(&List->ListSemaphore);
  128.  
  129.     if(List->ListNode)
  130.     {
  131.         if(List->ListNode->ln_Succ->ln_Succ)
  132.         {
  133.             Node = List->ListNode = List->ListNode->ln_Succ;
  134.  
  135.             List->ListOffset++;
  136.         }
  137.         else
  138.             Node = NULL;
  139.  
  140.         ReleaseSemaphore(&List->ListSemaphore);
  141.     }
  142.     else
  143.     {
  144.         ReleaseSemaphore(&List->ListSemaphore);
  145.  
  146.         Node = FirstGenericListNode(List);
  147.     }
  148.  
  149.     return(Node);
  150. }
  151.  
  152.     /* PrevGenericListNode(struct GenericList *List):
  153.      *
  154.      *    Pick the preceding node in a generic list.
  155.      */
  156.  
  157. struct Node *
  158. PrevGenericListNode(struct GenericList *List)
  159. {
  160.     struct Node *Node;
  161.  
  162.     SafeObtainSemaphoreShared(&List->ListSemaphore);
  163.  
  164.     if(List->ListNode)
  165.     {
  166.         if(List->ListNode->ln_Pred->ln_Pred)
  167.         {
  168.             Node = List->ListNode = List->ListNode->ln_Pred;
  169.  
  170.             List->ListOffset--;
  171.         }
  172.         else
  173.             Node = NULL;
  174.  
  175.         ReleaseSemaphore(&List->ListSemaphore);
  176.     }
  177.     else
  178.     {
  179.         ReleaseSemaphore(&List->ListSemaphore);
  180.  
  181.         Node = LastGenericListNode(List);
  182.     }
  183.  
  184.     return(Node);
  185. }
  186.  
  187.     /* DeleteGenericListNode(struct GenericList *List,struct Node *Node):
  188.      *
  189.      *    Delete a single node from a generic list.
  190.      */
  191.  
  192. struct Node *
  193. DeleteGenericListNode(struct GenericList *List,struct Node *Node,BOOL Notify)
  194. {
  195.     struct Node *Result;
  196.  
  197.     ObtainSemaphore(&List->ListSemaphore);
  198.  
  199.     if(List->Notify && Notify)
  200.         (*List->Notify)(List,0);
  201.  
  202.     if(!Node)
  203.         Node = List->ListNode;
  204.  
  205.     if(Node)
  206.     {
  207.         if(Node == List->ListNode)
  208.         {
  209.             if(Node->ln_Succ->ln_Succ)
  210.                 List->ListNode = Node->ln_Succ;
  211.             else
  212.             {
  213.                 if(Node->ln_Pred->ln_Pred)
  214.                 {
  215.                     List->ListNode = Node->ln_Pred;
  216.                     List->ListOffset--;
  217.                 }
  218.                 else
  219.                 {
  220.                     List->ListNode = NULL;
  221.                     List->ListOffset = -1;
  222.                 }
  223.             }
  224.  
  225.             Remove(Node);
  226.         }
  227.         else
  228.         {
  229.             Remove(Node);
  230.  
  231.             if(List->ListNode)
  232.             {
  233.                 struct Node *LocalNode;
  234.                 LONG i;
  235.  
  236.                 for(i = 0, LocalNode = (struct Node *)List->ListHeader.mlh_Head ; i < List->ListCount - 1 ; i++, LocalNode = LocalNode->ln_Succ)
  237.                 {
  238.                     if(LocalNode == List->ListNode)
  239.                     {
  240.                         List->ListOffset = i;
  241.                         break;
  242.                     }
  243.                 }
  244.             }
  245.         }
  246.  
  247.         FreeVecPooled(Node);
  248.  
  249.         List->ListCount--;
  250.     }
  251.  
  252.     if(List->Notify && Notify)
  253.         (*List->Notify)(List,1);
  254.  
  255.     Result = List->ListNode;
  256.  
  257.     ReleaseSemaphore(&List->ListSemaphore);
  258.  
  259.     return(Result);
  260. }
  261.  
  262.     /* CreateGenericListNode(LONG Size,STRPTR Name):
  263.      *
  264.      *    Create a new generic list node.
  265.      */
  266.  
  267. struct Node *
  268. CreateGenericListNode(LONG Size,STRPTR Name)
  269. {
  270.     struct Node    *Node;
  271.     LONG         Head;
  272.  
  273.     if(Size < sizeof(struct Node))
  274.         Head = Size = sizeof(struct Node);
  275.     else
  276.         Head = Size;
  277.  
  278.     if(Name)
  279.         Size += strlen(Name) + 1;
  280.  
  281.     if(Node = (struct Node *)AllocVecPooled(Size,MEMF_ANY | MEMF_CLEAR))
  282.     {
  283.         if(Name)
  284.         {
  285.             Node->ln_Name = ((char *)Node) + Head;
  286.  
  287.             strcpy(Node->ln_Name,Name);
  288.         }
  289.         else
  290.             Node->ln_Name = NULL;
  291.     }
  292.  
  293.     return(Node);
  294. }
  295.  
  296.     /* AddGenericListNode(struct GenericList *List,struct Node *Node,BYTE Mode):
  297.      *
  298.      *    Add a node to a generic list.
  299.      */
  300.  
  301. VOID
  302. AddGenericListNode(struct GenericList *List,struct Node *Node,LONG Mode,BOOL Notify)
  303. {
  304.     LONG Position = 0;
  305.  
  306.     ObtainSemaphore(&List->ListSemaphore);
  307.  
  308.     if(List->Notify && Notify)
  309.         (*List->Notify)(List,0);
  310.  
  311.     switch(Mode)
  312.     {
  313.         case ADD_GLIST_BOTTOM:
  314.  
  315.             AddTail((struct List *)&List->ListHeader,Node);
  316.             Position = List->ListCount;
  317.             break;
  318.  
  319.         case ADD_GLIST_TOP:
  320.  
  321.             AddHead((struct List *)&List->ListHeader,Node);
  322.             break;
  323.  
  324.         case ADD_GLIST_BEHIND:
  325.  
  326.             if(List->ListNode)
  327.             {
  328.                 Insert((struct List *)&List->ListHeader,Node,List->ListNode);
  329.                 Position = List->ListOffset + 1;
  330.             }
  331.             else
  332.             {
  333.                 AddTail((struct List *)&List->ListHeader,Node);
  334.                 Position = List->ListCount;
  335.             }
  336.  
  337.             break;
  338.  
  339.         case ADD_GLIST_BEFORE:
  340.  
  341.             if(List->ListNode && List->ListNode != (struct Node *)List->ListHeader.mlh_Head)
  342.             {
  343.                 Insert((struct List *)&List->ListHeader,Node,List->ListNode->ln_Pred);
  344.                 Position = List->ListOffset;
  345.             }
  346.             else
  347.                 AddHead((struct List *)&List->ListHeader,Node);
  348.  
  349.             break;
  350.     }
  351.  
  352.     List->ListNode = Node;
  353.     List->ListOffset = Position;
  354.     List->ListCount++;
  355.  
  356.     if(List->Notify && Notify)
  357.         (*List->Notify)(List,1);
  358.  
  359.     ReleaseSemaphore(&List->ListSemaphore);
  360. }
  361.  
  362.     /* GenericListCount(struct GenericList *List):
  363.      *
  364.      *    Return the number of generic list entries.
  365.      */
  366.  
  367. LONG
  368. GenericListCount(struct GenericList *List)
  369. {
  370.     LONG Count;
  371.  
  372.     SafeObtainSemaphoreShared(&List->ListSemaphore);
  373.  
  374.     Count = List->ListCount;
  375.  
  376.     ReleaseSemaphore(&List->ListSemaphore);
  377.  
  378.     return(Count);
  379. }
  380.  
  381.     /* RemoveFirstGenericListNode(struct GenericList *List):
  382.      *
  383.      *    Removes the first node of a generic list and
  384.      *    returns it. This is similar to RemHead().
  385.      */
  386.  
  387. struct Node *
  388. RemoveFirstGenericListNode(struct GenericList *List)
  389. {
  390.     struct Node *Node;
  391.  
  392.     ObtainSemaphore(&List->ListSemaphore);
  393.  
  394.     if(List->Notify)
  395.         (*List->Notify)(List,0);
  396.  
  397.     if(Node = RemHead((struct List *)&List->ListHeader))
  398.     {
  399.         List->ListCount--;
  400.  
  401.         if(Node == List->ListNode)
  402.         {
  403.             List->ListNode = NULL;
  404.             List->ListOffset = -1;
  405.         }
  406.         else
  407.             List->ListOffset--;
  408.     }
  409.  
  410.     if(List->Notify)
  411.         (*List->Notify)(List,1);
  412.  
  413.     ReleaseSemaphore(&List->ListSemaphore);
  414.  
  415.     return(Node);
  416. }
  417.  
  418. VOID
  419. LockGenericList(struct GenericList *List)
  420. {
  421.     if(List)
  422.         ObtainSemaphore(&List->ListSemaphore);
  423. }
  424.  
  425. VOID
  426. SharedLockGenericList(struct GenericList *List)
  427. {
  428.     if(List)
  429.         SafeObtainSemaphoreShared(&List->ListSemaphore);
  430. }
  431.  
  432. VOID
  433. UnlockGenericList(struct GenericList *List)
  434. {
  435.     if(List)
  436.         ReleaseSemaphore(&List->ListSemaphore);
  437. }
  438.  
  439. VOID
  440. SelectGenericListNode(struct GenericList *List,struct Node *Node,LONG Offset)
  441. {
  442.     ObtainSemaphore(&List->ListSemaphore);
  443.  
  444.     if(Node)
  445.     {
  446.         struct Node *ListNode;
  447.         LONG i;
  448.  
  449.         Offset = -1;
  450.  
  451.         for(i = 0, ListNode = (struct Node *)List->ListHeader.mlh_Head ; i < List->ListCount ; i++, ListNode = ListNode->ln_Succ)
  452.         {
  453.             if(ListNode == Node)
  454.             {
  455.                 Offset = i;
  456.                 break;
  457.             }
  458.         }
  459.     }
  460.     else
  461.         Node = GetListNode(Offset,(struct List *)List);
  462.  
  463.     if(Node != NULL && Offset >= 0)
  464.     {
  465.         List->ListNode        = Node;
  466.         List->ListOffset    = Offset;
  467.     }
  468.     else
  469.     {
  470.         List->ListNode        = NULL;
  471.         List->ListOffset    = -1;
  472.     }
  473.  
  474.     ReleaseSemaphore(&List->ListSemaphore);
  475. }
  476.